最後更新日:2023/01/09
[程式設計]使用.Net Core快速實作瀏覽器推播(Push Notifications)功能
瀏覽器推播通知(Push Notifications)對於網站製作者來說是個很好的功能,當使用者允許通知後,無論他有沒有停留在網站上,或是沒在用手機,都可以像APP通知那樣,將更新內容傳送給使用者,進而維持黏著度,以下就讓我們來快速的製作這個功能吧。
推播通知是利用了Service Worker,也就是瀏覽器的背景來執行運作的,要完成使用者訂閱、網站端發通知、使用者接收,需要下面幾個步驟:
- 準備好serviceWorker.js檔案,並放在網站根目錄。
- 取得VPID金鑰,防止任何人都可以傳送通知給這個使用者。
- 準備好一個html檔案,放置一個按鈕,撰寫相關javascript,使用者按下後會詢問是否給予通知的權限。
- 得到使用者權限後,取得回傳的endPoint、p256dh、auth值。
- 使用.Net Core來發送通知給使用者。
讓我們來開始吧!
1.準備好serviceWorker.js,並放在網站根目錄。
this.addEventListener('install', function(event) {
console.log('安裝service wroker');
});
this.addEventListener('activate', function(event){
console.log('service wroker已啟動!')
});
this.addEventListener('fetch', function(event) {
console.log('Handling fetch event for', event.request.url);
});
// controlling service worker
this.addEventListener("message", function(e) {
// e.source is a client object
e.source.postMessage("Hello! Your message was: " + e.data);
});
this.onpush = function(event) {
console.log(event.data);
// From here we can write the data to IndexedDB, send it to any open
// windows, display a notification, etc.
}
this.addEventListener('push', function (e) {
var body;
if (e.data) {
body = e.data.text();
} else {
body = "Standard Message";
}
var options = {
body: body,
icon: "/assets/img/xxxxx.jpeg", //顯示網站LOGO 絕對或相對路徑都可
image: '/assets/img/xxxxx.jpeg', //顯示通知的圖片 絕對或相對路徑都可
vibrate: [100, 50, 100],
data: {
dateOfArrival: Date.now()
},
actions: [
{
action: "explore", title: "瀏覽最新文章",
icon: "images/checkmark.png" //按鈕的icon圖 絕對或相對路徑都可
},
{
action: "close", title: "關閉",
icon: "images/red_x.png" //按鈕的icon圖 絕對或相對路徑都可
},
]
};
e.waitUntil(
self.registration.showNotification("露西的爹有新文章囉", options)
);
});
this.addEventListener('notificationclick', function (e) {
var notification = e.notification;
var action = e.action;
if (action === 'close') {
notification.close();
} else {
// 按下瀏覽最新文章要做的動作
clients.openWindow('https//www.lucysdad.com');
notification.close();
}
});
2.取得VPID金鑰,防止任何人都可以傳送通知給這個使用者,可直接上這個網站線上產生公鑰及私鑰,並留存等下使用。
3.準備好一個html檔案,放置一個按鈕,並設定click後要執行的function。
<button type="button" onclick="InstallServiceWorker()">
4.撰寫相關javascript,使用者按下後會詢問是否給予通知的權限。
function InstallServiceWorker() {
if ('serviceWorker' in navigator) { //判斷瀏覽器是否支援serviceWorker
navigator.serviceWorker
.register('/serviceworker.js') // 註冊 Service Worker 路徑為第一步驟的serviceworker.js
.then(function (reg) {
//console.log('Registration succeeded. Scope is ' + reg.scope); // 註冊成功 取消註解後會印出service worker可使用的範圍
//註冊後判斷使用者是否之前已經訂閱過了
if (Notification.permission === "granted") {
console.log("已經訂閱過了");
alert("您已經訂閱過囉");
getSubscription(reg);
} else if (Notification.permission === "blocked") {
console.log("之前拒絕了訂閱"); //可跳訊息視窗告知如何重新訂閱
} else {
console.log("還沒訂閱過");
requestNotificationAccess(reg); //顯示訂閱視窗
}
})
.catch(function (error) {
console.log('Registration failed with ' + error); // 註冊失敗
});
} else { //瀏覽器不支援serviceWorker 可能是版本太舊
alert("很抱歉,您的瀏覽器不支援訂閱的功能,請升級您的瀏覽器。");
}
}
function requestNotificationAccess(reg) {
Notification.requestPermission(function (status) {
if (status == "granted") {
//console.log("使用者按下訂閱了");
var options = {
body: '您已成功訂閱露西的爹!',
icon: '/assets/img/_____.jpg' //顯示網站LOGO 絕對或相對路徑都可
}
new Notification('訂閱完成!!', options); //即時發送一個通知,告訴使用者已完成訂閱
getSubscription(reg);
} else {
//console.log("使用者拒絕了訂閱");
}
});
}
function getSubscription(reg) {
reg.pushManager.getSubscription().then(function (sub) {
if (sub === null) {
reg.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: "BAEhJJK8pqg33cGF4pWcY.......HXNjUPtteNHcCf01jBVWY7018oQm9zQ" //這是步驟2所取得到的 public Key
}).then(function (sub) {
fillSubscribeFields(sub);
}).catch(function (e) {
console.error("Unable to subscribe to push", e);
});
} else {
fillSubscribeFields(sub);
}
});
}
function fillSubscribeFields(sub) {
//步驟五所提到的 得到使用者權限後,取得回傳的endPoint、p256dh、auth值
//可自行將這三個值透過ajax存入您的資料庫
console.log("sub.endpoint:" + sub.endpoint); //endPoint為要傳送通知時,每個人都有不同的api網址
console.log("p256dh:" + arrayBufferToBase64(sub.getKey("p256dh")));
console.log("auth:" + arrayBufferToBase64(sub.getKey("auth")));
}
function arrayBufferToBase64(buffer) {
var binary = '';
var bytes = new Uint8Array(buffer);
var len = bytes.byteLength;
for (var i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return window.btoa(binary);
}
5.得到使用者權限後,取得回傳的endPoint、p256dh、auth值,這部分已在上一步驟的fillSubscribeFields function裡完成。
6.使用.Net Core來發送通知給使用者,請先安裝WebPush-NetCore套件,接者撰寫以下程式。
var subject = "mailto:XXXXX@gmail.com"; //申請VAPID所輸入的email
var publicKey = "BAHWfhher623h....cfhFjFUjNKs"; //步驟2所取得到的 public Key
var privateKey = "privateKey-privateKey-privateKey-privateKey"; //步驟2所取得到的 private Key
var vapidDetails = new VapidDetails(subject, publicKey, privateKey);
PushSubscription subscription = new PushSubscription(
"https://fcm.googleapis.com/fcm/send/......", //步驟5得到的endPoint值
"BAct3KDe0CyW6Cc1De0CyW6CPxy.......De0CyW6C", //步驟5得到的p256dh值
"HRIePb8....UlftQ=="); //步驟5得到的auth值
var webPushClient = new WebPushClient();
try
{
webPushClient.SendNotification(subscription, "[居家風水]告別2022!2023年九宮飛星開運風水佈局", vapidDetails);
}
catch (Exception)
{
}
搞定收工,使用者收到的通知樣式可以在步驟一的this.addEventListener('push', function (e) {}監聽事件裡面完成。
本篇只是快速的帶各位完成使用者訂閱及網站端發送通知的功能,其中service worker的生命週期、使用範圍、監聽事件等等,有很多原理可以自行去研究,精進自己的程式能力。
參考網站:
https://blog.elmah.io/how-to-send-push-notifications-to-a-browser-in-asp-net-core/
https://ithelp.ithome.com.tw/users/20117813/ironman/2219
https://www.cythilya.tw/2018/02/17/firebase-push-notification/
0 則留言
露西的爹
Hi,我是露西的老爹,無聊時寫寫文章分享很多有用的資訊。
有新文章就會馬上通知哦!